.section .MATH_FUNC .text
//using registor x1,x2 and x3,x4 to regist numbers, X5 to mem (x1+x2)/(x3+x4)
//除法
.global L_DIV  
L_DIV:             
    LDR X2, [sp], #8   // 假设栈是向下增长的，加载值到 X2 并调整栈指针  
    LDR X1, [sp], #8  
    LDR X4, [sp], #8  
    LDR X3, [sp], #8  
    MOV X5, 0  
    CMP X2, X4  
    B.LT LITTLE_CASE  
DIV_CONTI:  
    CMP X2, X4  
    B.LT CAL_LITTLE_CASE  
    SUB X2, X2, X4  
S_CONTI:  
    CMP X1, X3  
    B.LT END_CASE  
    SUB X1, X1, X3  
    ADD X5, X5, 1 
    B DIV_CONTI  
LITTLE_CASE:   
    STR -1, [sp, #-8]! // 假设我们想要推送一个值到栈上，并调整栈指针  
    STR -1, [sp, #-8]! // 再次推送一个值（这通常不是好的做法，只是示例）  
    RET  
CAL_LITTLE_CASE:  
    CMP X1, X3  
    B.LT END_CASE  
    SUB X1, X1, 1  
    SUB X2, X2, X4  
    SUB X2, X2, 1      // 原来的 ADD X2, X2, -1 应该是 SUB X2, X2, 1  
    B S_CONTI  
END_CASE:  
    STR X5, [sp, #-16]!  
    STR X1, [sp, #-16]!  
    STR X2, [sp, #-16]! // 注意：这里我们假设有足够的栈空间来推送这些值  
    RET

//                             //using x1,x2,x3,x4,x5,x6,w1,w2 and return in stack in small-end storage mode
//乘法
.global L_MUL        
L_MUL:
    LDR x2, [sp], #8
    LDR x1, [sp], #8  
    LDR x3, [sp], #8  
    LDR x4, [sp], #8
    
    STR X2,[SP,#-8]!
    STR WZR, [sp, #-8]!
    LDR Q1,[SP],#16
    
    STR WZR, [sp, #-4]! 
    STR Q1,[SP],#4
    LDR W1,[SP],#4
    
    STR X4,[SP],#8
    LDR W2,[SP],#4
    LDR W2,[SP],#4
    
    STR W1,[SP,#-4]!
    STR WZR,[SP,#-4]!
    LDR X5,[SP],#8
    
    STR W2,[SP,#-4]!
    STR WZR,[SP,#-4]!
    LDR X6,[SP],#8
    MUL X5,X5,X6
    
    STR X5,[SP],#8
    LDR W1,[SP],#4
    LDR W1,[SP],#4
    
    STR WZR, [sp, #-4]! 
    STR W1, [sp, #-4]! 
    LSR X5,X5,#32
    
    STR X5,[SP],#8
    LDR W1,[SP],#4
    LDR W1,[SP],#4
    
    LSR X2,X2,#32
    LSR X4,X4,#32
    MUL X2,X2,X4
    ADD X2,X2,X4
    
    STR X2,[SP],#8
    LDR W1,[SP],#4
    LDR W1,[SP],#4
    
    STR WZR, [sp, #-4]!   
    STR W1, [sp, #-4]! 
    LSR X2,X2,#32
    
    STR X1,[SP],#8
    LDR W1,[SP],#4
    LDR W1,[SP],#4
    
    STR X3,[SP],#8
    LDR W2,[SP],#4
    LDR W2,[SP],#4

    STR X5,[SP],#8
    LDR W1,[SP],#4
    LDR W1,[SP],#4

    STR X6,[SP],#8
    LDR W2,[SP],#4
    LDR W2,[SP],#4
    MUL X5,X5,X6
    ADD X5,X5,X2

    STR X5,[SP],#8
    LDR W1,[SP],#4
    LDR W1,[SP],#4

    STR WZR, [sp, #-4]!  
    STR W1, [sp, #-4]!
    LSR X5,X5,#32
    LSR X1,X1,#32
    LSR X3,X3,#32
    MUL X1,X1,X3
    ADD X1,X1,X5

    STR X1,[SP],#8
    LDR W1,[SP],#4
    LDR W1,[SP],#4

    LSL X1,X1,#32
    LDR w1, [sp], #4
    ADD X1,X1,W1
    LDR w1, [sp], #4

    STR W1,[SP,#-4]!
    STR WZR,[SP,#-4]!
    LDR X2,[SP],#8

    LSL X2,X2,#32
    LDR w1, [sp], #4
    ADD X2,X2,W1
    STR X1, [sp, #-16]!  
    STR X2, [sp, #-16]!
    RET

////using x1,x2,x3,x4 return in stack in small-end storage mode
//减法
.global L_SUB          
L_SUB:
    LDR X2, [sp], #8  // 加载x2并调整栈指针  
    LDR X1, [sp], #8  
    LDR X4, [sp], #8  
    LDR X3, [sp], #8
    CMP X1,X3
    B.LT L_SUB_MINUS
L_SUB_CONTINUE:
    CMP X2,X4
    B.LT L_SUB_BORROW
    SUB X2,X4
    SUB X1,X3
    STR X2, [sp, #-8]! 
    STR X1, [sp, #-8]!
    RET
L_SUB_MINUS:
    EOR X1,X1,X3
    EOR X3,X1,X3
    EOR X1,X1,X3
    EOR X2,X2,X4
    EOR X4,X2,X4
    EOR X2,X2,X4
    B L_SUB_CONTINUE
L_SUB_BORROW:
    SUB X1,X1,#1
    CMP X1,X3
    B.LT L_SUB_LT
    SUB X2,X2,X4
    MOV X4,0
    B L_SUB_CONTINUE
L_SUB_LT:
    ADD X1,X1,#1
    B L_SUB_MINUS

//                               //THIS FUNCTION NEEDS NEON
//                                 //using Q1,Q2,Q3,Q4,x6,x7 and return the key in stack in small-end storage mode
//拓展欧拉函数求出私密
.global EXTEND_EU               
EXTEND_EU:                     
    LDR Q1, [sp], #16
    LDR Q2, [sp], #16 
    LDR Q3, [sp], #16 
    LDR Q4, [sp], #16   
    STR lr, [sp, #-8]!  
    MOV x7, 0             
EU_CONTTI:
    ADD X7,X7,#1
    CMP Q1,0
    B.EQ EU_NEXT
    STR Q1, [sp, #-16]!
    STR Q1, [sp, #-16]!
    
    STR Q2, [SP,#-16]!
    LDR Q6, [SP], #16
    
    STR Q1, [sp, #-16]!
    STR Q2, [sp, #-16]!
    BL L_DIV
    LDR Q2, [sp], #16
    LDR X6, [sp], #8
    STR Q2, [SP,#-16]!
    LDR Q1, [SP], #16
    B EU_CONTTI
EU_NEXT:
    STR Q1, [SP,#-16]!
    LDR Q5, [SP], #16
    MOV X1,1
    STR X1,[SP],#8
    STR WZR,[SP],#8
    LDR Q3,[SP,#-16]!
    
    MOV X1,0
    STR X1,[SP],#8
    STR WZR,[SP],#8
    LDR Q4,[SP,#-16]!
EU_WHILE:
    CMP X7,0
    B.EQ EU_OUT
    LDR Q2, [sp], #16
    LDR Q1, [sp], #16
    STR Q1, [sp, #-16]!
    STR Q2, [sp, #-16]!
    BL L_DIV
    STR Q6, [sp, #-16]!
    LDR X6, [sp], #8
    
    STR X6,[SP,#-8]!
    STR WZR, [sp, #-8]!
    LDR Q6,[SP],#16
    
    STR Q6, [sp, #-16]!
    STR Q3, [sp, #-16]!
    BL L_MUL
    LDR Q6, [sp], #16
    STR Q6, [sp, #-16]!
    STR Q4, [sp, #-16]!
    BL L_SUB
    LDR Q4, [sp], #16
    EOR Q3,Q3,Q4
    EOR Q4,Q3,Q4
    EOR Q3,Q3,Q4
    SUB X7,X7,#1
    B EU_WHILE
EU_OUT:
    LDR LR, [sp], #8
    STR Q1, [SP,#-16]!
    RET

//快速幂
//                             //THIS FUNCTION NEEDS NEON 
//                             //using Q1,Q2,Q3,Q4,Q5,x3
.global FAST_PM                 
FAST_PM:                     
    LDR Q1, [sp], #16 
    LDR Q2, [sp], #16 
    LDR Q3, [sp], #16
    STR lr, [sp, #-8]!
    MOV X1,1
    STR X1,[SP,#-8]!
    STR WZR,[SP,#-8]!
    LDR Q4,[SP],#16
    STR Q3, [sp, #-16]!
    STR Q1, [sp, #-16]!
    BL L_DIV
    LDR Q1, [sp], #16 
    LDR X3, [sp], #8
FPM_WHILE:
    CMP Q2,WZR
    B.EQ FPM_END
    
    STR Q2,[SP,#-16]!
    LDR Q5,[SP],#16
    
    STR Q2, [sp, #-16]!
    LDR Q5,[SP],#16

    LSR Q2,Q2,#1
    LSL Q2,Q2,#1
    EOR X3,Q2,Q5
    CMP X3,0
    B.EQ FPM_NEXT
    STR Q4, [sp, #-16]!
    STR Q1, [sp, #-16]!
    BL L_MUL
    LDR Q4, [sp], #16
    STR Q3, [sp, #-16]!
    STR Q4, [sp, #-16]!
    BL L_DIV
    LDR Q4, [sp], #16
    LDR X3, [sp], #8
FPM_NEXT:
    LSR Q2,Q2,#1
    STR Q1, [sp, #-16]!
    STR Q1, [sp, #-16]!
    BL L_MUL
    LDR Q1, [sp], #16 
    STR Q3, [sp, #-16]!
    STR Q1, [sp, #-16]!
    BL L_DIV
    LDR Q1, [sp], #16 
    LDR X3, [sp], #8
    B FPM_WHILE
FPM_END:
    LDR LR, [sp], #8
    STR Q4, [sp, #-16]!
    RET
